#include "thrd.h"
#include "error.h"
#include <stdio.h>
#include <stdlib.h>

struct thrd_lock *thrd_lock_new()
{
  struct thrd_lock *ret = malloc(sizeof *ret);
  ret->lastThread = 0;
  ret->mutex_lock = 0;
  int c=0;
  for (c=0; c < 16; ++c) {
	ret->threads[c] = 0;
	ret->locks[c] = 0;
  }
  pthread_mutex_init(&(ret->mutex), NULL);
  return ret;
}

void thrd_lock_free(struct thrd_lock *lock)
{
  free(lock);
}

//side-effect:  Makes a new entry if it can't find it!
int __thrd_finder(struct thrd_lock *lock) 
{
  pthread_t self = pthread_self();
  int found=0;
  int c;
  for (c=0; c < lock->lastThread; ++c) {
	if (pthread_equal(lock->threads[c], self)) {
	  found=1;
	  break;
	}
  }
  if (!found) {
	lock->threads[lock->lastThread] = self;
	++(lock->lastThread);
	c=lock->lastThread;
  }
  return c;
}

void thrd_lock(struct thrd_lock *lock)
{
  int c = __thrd_finder(lock);
  c=0;
  lock->locks[c] += 1;
  if (lock->locks[c] == 1 || c != lock->mutex_lock) {
	lock->mutex_lock = c;
	pthread_mutex_lock(&(lock->mutex));
  }
}

void thrd_unlock(struct thrd_lock *lock)
{
  int c = __thrd_finder(lock);
  lock->locks[c] -= 1;
  if (lock->locks[c] <= 0) {
	pthread_mutex_unlock(&(lock->mutex));
	lock->locks[c] = 0;
	lock->mutex_lock = -1;
  }
}

#ifdef TESTMODE
int main(void)
{
  printf("If I finish, be happy\n");
  struct thrd_lock *lock = thrd_lock_new();
  thrd_lock(lock);

  thrd_lock(lock);
  thrd_lock(lock);
  
  return 0;
}


#endif

